import {celebrate, Joi} from "celebrate";
import {withLock} from "easylock";
import * as express from "express";
import {Request} from "express";
import ms = require("ms");
import * as request from 'superagent'
import {InstanceType} from "typegoose";
import {isNullOrUndefined} from "util";
import {alipayCashier} from "../alipay/payment";
import {GameActivityModel} from "../database/models/gameActivity";
import {LipstickGameOrderModel} from "../database/models/lipstickGameOrder";
import {LipstickSeries, LipstickSeriesModel, PlayerSeriesIncomeModel} from "../database/models/lipstickSeries";
import {Product, RMB_2_COIN_RATE,} from "../database/models/Product";
import {DEFAULT_THRESHOLD_RATE, SeriesIncomeThresholdModel} from "../database/models/seriesIncomeThreshold";
import {wechatPayCashier} from "../wechat/wechatCashier";
import {InternalError} from "./error";
import {LipStickGame} from "./games/lipStickGame";
import {Response, withActivity, withLipstickSeries, withUser} from "./middlewareType"
import {jwtAuthMiddleware} from "./passort";
import {maxAry} from "./product";
import {CLIENT_TYPE, lipstickResumeTimes, pcUrl} from "./utils";

const router = express.Router()

router.get('/',
  jwtAuthMiddleware,
  async (req: Request & withUser, res: Response) => {
    try {
      const lipstickSerieses = await LipstickSeriesModel.find({category: `lipstick`, onStock: true})
        .sort({hotNum: 1, createAt: -1})
        .lean()
      const sorted = [].concat(lipstickSerieses)
      const hots = maxAry(lipstickSerieses, 4)
      const final = Array.from(new Set([...hots, ...sorted]))

      for (const it of final) {
        const psi = await PlayerSeriesIncomeModel.findOne({
          lipstickSeries: it,
          player: req.user.id
        })

        if (!psi) {
          it.canUse = false
          it.percentage = 0
          continue
        }

        let rate = DEFAULT_THRESHOLD_RATE
        const sit = await SeriesIncomeThresholdModel.findOne({lipstickSeries: it._id})
        if (sit)
          rate = sit.thresholdCoinRate

        const threshold = it.seriesPrice * RMB_2_COIN_RATE * rate

        it.canUse = psi.income >= threshold
        it.percentage = psi.income / threshold
      }

      res.json({ok: true, data: {lipstickSerieses: final}})
    } catch (e) {
      res.error(e)
    }

  })

router.get('/:lipstickSeriesId',
  jwtAuthMiddleware,
  async (req: Request & withUser, res: Response) => {
    try {
      const lipstickSeries =
        await LipstickSeriesModel.findOne({_id: req.params.lipstickSeriesId, onStock: true})
          .select({onStock: 0})
          .populate(`products`)
          .lean()

      if (!lipstickSeries)
        throw InternalError("NO_SUCH_SERIES")

      const psi = await PlayerSeriesIncomeModel.findOne({
        lipstickSeries,
        player: req.user.id
      })
      if (!psi) {
        lipstickSeries.canUse = false
        lipstickSeries.percentage = 0
      } else {
        let rate = DEFAULT_THRESHOLD_RATE
        const sit = await SeriesIncomeThresholdModel.findOne({lipstickSeries: lipstickSeries._id})
        if (sit)
          rate = sit.thresholdCoinRate

        const threshold = lipstickSeries.seriesPrice * RMB_2_COIN_RATE * rate

        lipstickSeries.canUse = psi.income >= threshold
        lipstickSeries.percentage = psi.income / threshold
      }

      const lipProductsOn = []
      if (lipstickSeries.products) {
        for (const it of lipstickSeries.products as Product[]) {
          if (it.state === 'on')
            lipProductsOn.push(it)
        }
      }
      const ls = {
        ...lipstickSeries,
        products: lipProductsOn
      }
      res.json({ok: true, data: {lipstickSeries: ls}})

    } catch (e) {
      res.error(e)
    }
  })

router.post('/lipstickGameOrder/:activityId',
  jwtAuthMiddleware,
  celebrate({
      params: Joi.object().keys({activityId: Joi.string().required()}),
      body: Joi.object().keys({
        payType: Joi.string().required().valid([`coin`, `wechatPay`, `aliPay`]),
        clientType: Joi.string()
      })
    }
  ),
  async (req: Request & withActivity & withLipstickSeries, res: Response, next) => {
    if (req.body.payType !== `coin`) {
      console.log(`${__filename} lipstickGameOrder rmb开始游戏移除`)
      return
    }
    const activity = await GameActivityModel
      .findOne({_id: req.params.activityId, state: `done`})
      .populate(`lipstickSeries`)
    if (!activity)
      return res.error(InternalError(`ALREADY_CLAIMED`))

    if (activity.resumeTimes >= lipstickResumeTimes)
      return res.error(InternalError(`OVER_RESUME_LIMIT`))

    if (!activity.lipstickSeries)
      return res.error(InternalError(`NO_SUCH_SERIES`))

    req.activity = activity
    req.lipstickSeries = activity.lipstickSeries as InstanceType<LipstickSeries>
    next()
  },
  async (req: Request & withUser & withLipstickSeries, res, next) => {
    if (isNullOrUndefined(req.body.clientType) || req.body.clientType === CLIENT_TYPE.NORMAL) {
      if (req.user.coin + req.user.freeCoin < req.lipstickSeries.priceInCoin)
        return res.json(
          {
            ok: false, error: 'NO_ENOUGH_COIN',
            msg: '金币不足'
          })
      else
        next()
    } else if (req.body.clientType === CLIENT_TYPE.PUCHENG) {
      const re = await request.post(pcUrl + `/provideForOtherGame/gemIsEnough`)
        .send({
          gem: req.lipstickSeries.priceInFangka,
          wechatUnionid: req.user.wechatUnionid,
        })
        .then(r => {
          if (r && r.body && r.body.ok) {
            return r.body
          } else {
            return {ok: false}
          }
        }).catch(e => {
          console.error(pcUrl + '/provideForOtherGame/gemIsEnough ERROR', e)
          return {ok: false}
        })
      if (!re || !re.ok)
        return res.json(
          {
            ok: false, error: 'NO_ENOUGH_COIN',
            msg: '房卡不足'
          })
      else
        next()
    }
  },
  async (req: Request & withActivity & withUser & withLipstickSeries, res: Response) => {
    try {
      return await withLock(req.activity.id, async () => {
        const activity = req.activity
        const lipstickSeries = req.lipstickSeries as InstanceType<LipstickSeries>

        if (req.body.payType === `coin`) {

          const game = new LipStickGame(req.user, req.lipstickSeries, req.body.clientType || CLIENT_TYPE.NORMAL)
          const {ok, data} = await game.resume(req.activity)

          if (!ok)
            return res.error(InternalError(data.message))

          return res.json({
            ok: true,
            data: {
              canWin: data.canWin,
              activity: data.activity
            }
          })
        } else {
          console.log(`${__filename} lipstickGameOrder rmb开始游戏移除`)
          return

          // @ts-ignore
          const lgo = new LipstickGameOrderModel({
            activity,
            lipstickSeries: req.lipstickSeries,
            player: req.user.id,
            state: 'unpaid',
            payFor: 'resume',
            createAt: new Date()
          })
          await lgo.save()

          const paymentArg = {
            title: `lipstickgame resume`,
            detail: lipstickSeries.name,
            price: lipstickSeries.priceInCoin / RMB_2_COIN_RATE,
            order: lgo.id,
            type: 'LipstickGameOrder',
            fromIP: req.ip
          }

          const cashier = req.body.payType === 'wechatPay' ? wechatPayCashier : alipayCashier

          const payOrder = await cashier.createPaymentOrder(paymentArg, ms('15min'))

          return res.json({
            ok: true,
            data: {
              lipstickGameOrder: lgo,
              payOrder: payOrder.prepay
            }
          })
        }
      })
    } catch (e) {
      res.error(e)
    }
  }
)

export default router
